package com.tanhua.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.mapper.AdministratorMapper;
import com.tanhua.pojo.Administrator;
import com.tanhua.vo.AdministratorVo;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: cuixu
 * @Description: 类内容说明
 * @Date: Created in 10:15 2021/1/17
 * @ModifiedBy:
 */
@Service
@Slf4j
public class AdministratorService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private static final String redisKey = "CACHE_KEY_TOKEN_LOGIN";

    private static final String CACHE_KEY_TOKEN_PREFIX = "MANAGE_TOKEN_";

    private static final Logger LOGGER = LoggerFactory.getLogger(AdministratorService.class);

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private AdministratorMapper administratorMapper;

    //验证码
    private static final String CACHE_CODE_PREFIX = "MANAGE_CAP_";

    public void saveVerification(String uuid,String code) {
        //将验证码存入redis,设置有效时间为5分钟
        String key= CACHE_CODE_PREFIX + uuid;
        this.redisTemplate.opsForValue().set(key,code, Duration.ofMinutes(5));
    }
    
    /** 
     * @Description: 方法说明   
     * @param:
     * @return:  
     * @Author: cuixu    
     * @Date: 2021/1/17 
     */ 
    public String login(String username, String password, String verificationCode, String uuid) {

        //判断用户名密码是否为空
        if (StringUtils.isEmpty(username)) {
            return null;
        }
        if (StringUtils.isEmpty(password)) {
            return null;
        }


        //设置查询条件
        QueryWrapper<Administrator> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        Administrator administrator = this.administratorMapper.selectOne(queryWrapper);
        if (null == administrator) {
            return null;
        }

        String pw = DigestUtils.md5Hex(password);
        //判断用户输入密码是否一致
        if (!StringUtils.equals(pw, administrator.getPassword())) {
            return null;
        }

        String redisKey = CACHE_CODE_PREFIX + uuid;
        String value = this.redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(value)) {
            return null;
        }

        //System.out.println(value);
        //System.out.println(verificationCode);


        //判断存入redis中和输入的验证码是否一致
        if (!StringUtils.equalsIgnoreCase(value, verificationCode)) {
            return null;
        }

        //走到这里说明验证码正确，删除redis中的验证码
        this.redisTemplate.delete(redisKey);


        // 将账号和用户id封装成map集合，然后生成token
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("username", administrator.getUsername());
        claims.put("id", administrator.getUid());

        // 生成token
        String token = Jwts.builder()
                //设置响应数据体
                .setClaims(claims)
                //设置加密方法和加密盐
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
        try {
            // 将token存储到redis中
            String redisTokenKey = "CACHE_KEY_TOKEN_LOGIN" + token;
            //将密码设置为null，不参与序列化
            administrator.setPassword(null);
            String redisTokenValue = MAPPER.writeValueAsString(administrator);
            this.redisTemplate.opsForValue().set(redisTokenKey, redisTokenValue, Duration.ofDays(7));
            return token;
        } catch (Exception e) {
            LOGGER.error("保存token出错", e);
            return null;
        }
    }


    public AdministratorVo queryAdministratorByToken(String token) {

        try {
            String redisTokenKey = redisKey + token;
            String cacheData = redisTemplate.opsForValue().get(redisTokenKey);
            if (StringUtils.isEmpty(cacheData)) {
                return null;
            }
            redisTemplate.expire(redisTokenKey, 1, TimeUnit.HOURS);
            Administrator administrator = MAPPER.readValue(cacheData, Administrator.class);
            System.out.println(administrator);
            AdministratorVo administratorVo = new AdministratorVo();
            administratorVo.setUid(String.valueOf(administrator.getUid()));
            administratorVo.setUsername(administrator.getUsername());
            administratorVo.setAvatar(administrator.getAvatar());
            return administratorVo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void removeToken(String token) {
        String redisTokenKey = redisKey + token;
        this.redisTemplate.delete(redisTokenKey);
    }
}
